package com.wuyou.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.wuyou.convert.ConvertDtoToDO;
import com.wuyou.domain.vo.EsHouseVO;
import com.wuyou.domain.vo.HouseVO;
import com.wuyou.dto.HouseInputInfoDTO;
import com.wuyou.entity.*;
import com.wuyou.mapper.*;
import com.wuyou.service.IHouseService;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.index.query.*;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author cxy
 * @since 2022-09-29
 */
@Service
public class HouseServiceImpl extends ServiceImpl<HouseMapper, House> implements IHouseService {

    @Resource
    private HouseMapper houseMapper;

    @Resource
    private HouseDetailsMapper houseDetailsMapper;

    @Resource
    private HouseFurnitureMapper houseFurnitureMapper; //设施

    @Resource
    private HouseTagMapper houseTagMapper;

    @Resource
    private CommunityMapper communityMapper; // 小区

    @Autowired
    private RestHighLevelClient restHighLevelClient;


    @Override
    public PageInfo<HouseVO> findHouseInfoList(HouseVO houseVO,Integer pageNum, Integer pageSize) {
        PageHelper.startPage(pageNum, pageSize);
        PageInfo<HouseVO> pageInfo = new PageInfo(houseMapper.findHouseInfoList(houseVO));
        return pageInfo;
    }

    /**
     * 增加房屋信息
     * <p>
     * 1. 先增加小区信息 返回主键  给房屋详情信息 添加小区id
     * 2. 增加 房屋信息 返回主键  用来添加标签房屋中间表 房屋设施中间表  详情表
     * 3. 获取前台传过来的标签id  增加标签房屋中间表
     * 4. 取前台传过来的设施id   增加房屋设施中间表
     * 5. 省市县id 房屋id 小区id 添加详情表
     *
     * @param houseInputInfoDTO
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void insertHouseInfo(HouseInputInfoDTO houseInputInfoDTO) {

        //小区
        Community community = ConvertDtoToDO.convert2Community(houseInputInfoDTO);
        communityMapper.insert(community);
        Long communityId = community.getCommunityId();

        //房屋
        House house = ConvertDtoToDO.convert2House(houseInputInfoDTO);
        houseMapper.insert(house);
        Long houseId = house.getHouseId();

        // 详情
        HouseDetails houseDetails = ConvertDtoToDO.convert2HouseDetail(houseInputInfoDTO, communityId, houseId);
        houseDetailsMapper.insert(houseDetails);
        // Long houseDetailsId = houseDetails.getHouseDetailsId();

        // 房屋标签中间表
        for (Long tagId : houseInputInfoDTO.getTagId()) {
            houseTagMapper.insert(HouseTag.builder().houseId(houseId).tagId(tagId).build());
        }

        // 房屋设施中间表
        for (Integer furnitureId : houseInputInfoDTO.getFurnitureId()) {
            houseFurnitureMapper.insert(HouseFurniture.builder().furnitureId(furnitureId).houseId(houseId).build());
        }

    }


    enum HOUSE_FIELD_ENUM {
        // 已出租
        RENTED("status", 1),
        // 未出租
        NOT_RENTED("status", 0),
        // 审核通过
        AUDIT("audit", 1);

        private String statusStr;
        private int statusCode;

        HOUSE_FIELD_ENUM(String statusStr, int statusCode) {
            this.statusStr = statusStr;
            this.statusCode = statusCode;
        }
    }


    /**
     * 批量审核
     *
     * @param houseIds
     * @param auditStatus
     */
    @Override
    public void auditHouse(Long[] houseIds, int auditStatus) {
        houseMapper.auditHouse(houseIds,auditStatus);
    }

    @Override
    public List<HouseVO> multiConditionFindHouse(EsHouseVO esHouseVO, Integer pageNum, Integer pageSize) throws Exception{

        // 搜索请求对象
        SearchRequest searchRequest = new SearchRequest("house");
        // 搜索源构建对象
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        //创建复合查询工具
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
        RangeQueryBuilder rangeQueryBuilder= null;
        //设置查询条件:
        if (esHouseVO != null) {
            if (esHouseVO.getStartPrice() != null) {
                rangeQueryBuilder = QueryBuilders.rangeQuery("rent").gte(esHouseVO.getStartPrice()).lte(esHouseVO.getEndPrice());
                //添加过滤条件
                boolQueryBuilder.filter(rangeQueryBuilder);
            }
            if ( esHouseVO.getHouseType() != null) {
                TermQueryBuilder housetype = QueryBuilders.termQuery("housetype", esHouseVO.getHouseType());
                boolQueryBuilder.filter(housetype);
            }
            if (esHouseVO.getStartTimeSort() != null && esHouseVO.getStartTimeSort().equals("DESC")) {
                searchSourceBuilder.sort("starttime", SortOrder.DESC);
            }else if (esHouseVO.getStartTimeSort() != null && esHouseVO.getStartTimeSort().equals("ASC")){
                searchSourceBuilder.sort("starttime", SortOrder.ASC);
            }
            if (esHouseVO.getRentSort() != null && esHouseVO.getRentSort().equals("DESC")) {
                searchSourceBuilder.sort("rent", SortOrder.DESC);
            }else if(esHouseVO.getRentSort() != null && esHouseVO.getRentSort().equals("ASC")){
                searchSourceBuilder.sort("rent", SortOrder.ASC);
            }
        }

        //分页
        // 计算起始下标：当前页数-1乘以页大小
        int index = (pageNum - 1) * pageSize;
        searchSourceBuilder.from(index);
        searchSourceBuilder.size(pageSize);
        // 聚合查询
        if (boolQueryBuilder != null) {
            searchSourceBuilder.query(boolQueryBuilder);
        }
        // 向搜索请求对象中设置搜索源
        searchRequest.source(searchSourceBuilder);
        SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
        // 搜索结果
        SearchHits hits = searchResponse.getHits();
        List<HouseVO> houseVOS = new ArrayList<HouseVO>();
        for (SearchHit hit : hits) {
            Map<String, Object> sourceAsMap = hit.getSourceAsMap();
            HouseVO houseVo = JSON.parseObject(JSON.toJSONString(sourceAsMap), HouseVO.class);
            houseVOS.add(houseVo);
        }
        return houseVOS;
    }
}
